const tool = require('ToolUtil');
const ProtoManager = require('PBManager');
const packet = require('CommonPacket');
var NetManager = cc.Class({
    extends: cc.Component,
    properties: {
        _isConnect: null, //是否连接
        _socket: null,
        _blockQueue: null, //等待消息对列
        _blockTime: 0, //需要等待的时间
        _blockCount: 0,
        _maxBlockCount: 0,
        _blockPakcetID: 0, //锁定时的ID
        _connectListener: null,
        _scenePlay: null,
        _callBack: null,
        _gameUrl: null,
        _disConnectBackToHall: null,
        _isReconnect: null,
        _foreventName: null,
        _foreventMsg: null,
        mCloseTime: null,
        _handlerMap: null,
        _gameHandler: null,
        _gamedict: null,
        _gameID: 0,
    },

    ctor: function () {
        this._handlerMap = []; //数据包 能用的
        this._gameHandler = [];
        this._isConnect = true; //是否连接
        this._socket = null;
        this._blockQueue = null; //等待消息对列
        this._blockTime = 0; //需要等待的时间
        this._blockCount = 0;
        this._maxBlockCount = 0.4;
        this._blockPakcetID = 0; //锁定时的ID
        this._connectListener = null;
        this._scenePlay = null;
        this._callBack = null;
        this._gameUrl = null;
        this._disConnectBackToHall = false;
        this._isReconnect = false;
        this._foreventName = null;
        this._foreventMsg = null;
        this.mCloseTime = null;
        this.mIsPlayRecord = false;
        this._gamedict = {}; //游戏对应的场景

        packet.CommonPacketInfo.forEach(item => {
            if (item.fn) {
                this.addHandler(item.name, item.fn, this);
            }
        });
    },

    registGameInfo: function (gameid, scenename, packetname, gameaction) {
        this._gamedict[gameid] = {
            scene: scenename,
            packet: packetname
        }

        if (gameaction !== undefined)
            tool.PlayerManager().registerAction(gameid, gameaction);
    },

    getScene: function (gameid) {
        return this._gamedict[gameid].scene;
    },

    getGameScene: function () {
        return this.getScene(this._gameID);
    },



    setOnConnectListnener: function (c) {
        this._connectListener = c;
    },

    createIO: function (url, callBack, isReconnect) {
        if (cc.sys.isNative)
            this._socket = SocketIO.connect(url, {
                "force new connection": true,
                "reconnection": false
                // "timeout": 10000
            });
        else
            this._socket = io(url, {
                "force new connection": true,
                "reconnection": false
                // "timeout": 100
            });

        this._socket.on('error', function (err) {
            cc.log(' this._socket.on(error)');
            this.onDisConnect(err);
            if (callBack) {
                callBack('error');
            }
        }.bind(this));
        this._socket.on('connect', function () {
            cc.log(' this._socket.on(connect)');
            this.onConnect();
            // showMessageBox('进入游戏成功 连接耗时为' + (new Date().getTime() - this.mStartTime));
            if (callBack) {
                callBack('connect');
            }
        }.bind(this));
        this._socket.on('connect_timeout', function () {
            cc.log(' this._socket.on(connect_timeout)');
            this.onConnectFailed(isReconnect);
            if (callBack) {
                callBack('connect_timeout');
            }
        }.bind(this));
        this._socket.on('connect_error', function () {
            cc.log(' this._socket.on(connect_error)');
            this.onConnectFailed(isReconnect);
            if (callBack) {
                callBack('connect_error');
            }
        }.bind(this));

        this._socket.on('disconnect', function () {
            cc.log(' this._socket.on(disconnect)');
            this.onDisConnect('连接断开');
            if (callBack) {
                callBack('disconnect');
            }
        }.bind(this));
    },
    // LIFE-CYCLE CALLBACKS:

    /**
     * 
     * @param {*} url 
     * @param {*} gameid 
     * @param {*} callBack 
     * @param {*} isReconnect 
     */
    connect: function (url, gameid, callBack, isReconnect) {
        if (this.mCloseTime == null)
            this.mCloseTime = 0;
        this._isReconnect = isReconnect;
        this._callBack = callBack;
        this._gameUrl = url;
        this._blockTime = 0;
        this._disConnectBackToHall = true;
        this._scenePlay = null;
        this.stopForeverMsg();
        this._blockQueue = [];
        this.mStartTime = new Date().getTime()
        if (typeof (gameid) == 'string') {
            gameid = Number.parseInt(gameid);
        }

        if (gameid == null) {
            var type = url.split(".");
            if (tyep[0].length > 0 && type[0] != "http" && type[0] != "https") {
                if (type == 'jscsmj') {
                    gameid = 1;
                } else if (type == 'jspdk') {
                    gameid = 3;
                } else if (type == 'xc') {
                    gameid = 7;
                } else if (type == 'phz') {
                    gameid = 6;
                } else if (type == 'nzl') {
                    gameid = 9;
                }
            }
        }
        if (this._gamedict[gameid] === undefined) {
            cc.windowManager.dismissWindowByName('loadingwin');
            tool.showMessageBox("未注册游戏相关数据");
            return;
        }
        this._gameID = gameid;
        this.createIO(url, callBack, isReconnect);

    },

    reconnect: function (isShowWin) {
        if (this._isConnect)
            return;
        if (this._gameUrl == null || this._gameUrl.length == 0)
            return;
        if (isShowWin) {
            cc.windowManager.showWindowByNameWithDate('loadingwin', "重新连接服务器中，请稍等...");
        }
        setTimeout(function () {
            this.connect(this._gameUrl, this._gameID, null, true);
        }.bind(this), 1000);
    },

    stopForeverMsg: function () {
        this._foreventName = null;
        this._foreventMsg = null;
        // this.node.removeChildByTag(421);
        // SceneManager.m_MainScene.removeChildByTag(421);
    },

    sendPacketForever: function (name, data) {
        if (this._foreventName && this._foreventName.length > 0) {
            this.stopForeverMsg();
        }
        this._foreventName = name;
        this._foreventMsg = data;
        // var tmp = new cc.Sprite();
        // tmp.setTag(421);
        // this.node.addChild(tmp);
        // // SceneManager.m_MainScene.addChild(tmp);

        // tmp.runAction(cc.sequence(cc.delayTime(0.3), cc.callFunc(this.sendAutoMsg, this)).repeatForever());
    },

    sendAutoMsg: function () {
        if (NetManager._foreventName && NetManager._foreventName.length > 0) {
            NetManager.sendPacket(NetManager._foreventName, this._foreventMsg);
        } else {
            NetManager.stopForeverMsg();
        }
    },

    sendPacket: function (name, data) {
        if (!this._isConnect || this._socket == null) {
            return;
        }
        if (data != '') {
            cc.log('数据包发送[' + name + ']:' + JSON.stringify(data));
        }
        this._socket.emit(name, data = this.enCode(name, data));

        // var p = PacketManager.getCSPacket(name);
        // if (p) {
        //     cc.log('数据包发送[' + name + ']:' + p.getData(this._scenePlay, data));
        //     this._socket.emit(name, data = this.enCode(name, data));
        // } else {
        //     cc.log('数据包发送失败 未注册消息包:' + name);
        // }
    },

    //每0.1秒判断一下
    update: function () {
        if (new Date().getTime() - this._blockTime >= 100 && this._blockQueue.length > 0) {
            // cc.log(' new Date().getTime() - this._blockTime = ' + (new Date().getTime() - this._blockTime) + ' this._blockQueue =' + this._blockQueue.length);
            var msg = this._blockQueue.shift();
            this._blockPakcetID = msg.name;
            if (this._blockTime < new Date().getTime() + 1000) {
                this.block(10); //10就是1秒
            }
            this.handler(msg.name, msg.data, false);
        }
    },

    //延时时间
    block: function (time) {
        if ((new Date().getTime() + time * 1000) > this._blockTime)
            this._blockTime = new Date().getTime() + time * 1000;
    },

    unblock: function (id) {
        if (typeof (id) != 'undefined' && this._blockPakcetID != 0 && id != this._blockPakcetID) {
            cc.log('要解除锁定的消息包[' + id + '] 与当前锁定的消息包[' + this._blockPakcetID + ']不符合');
            return;
        }
        this._blockTime = new Date().getTime();
        this._blockPakcetID = 0;
    },

    hasGameHandler: function () {
        if (this._gameHandler[this._gameID] === undefined)
            return false;
        if (Object.keys(this._gameHandler[this._gameID]).length == 0)
            return false;
        return true;
    },

    addGameHandler: function (gameid, name, cb, target) {
        if (typeof (gameid) == 'string') {
            target = cb;
            cb = name;
            name = gameid;
            gameid = this._gameID;
        }
        if (this._gameHandler[gameid] === undefined) {
            this._gameHandler[gameid] = {};
        }
        this._gameHandler[gameid][name] = {
            callBack: cb,
            target: target
        };
    },

    addHandler: function (name, cb, target) {
        if (this._handlerMap[name] !== undefined) {
            cc.log('已经注册，即将覆盖');
        }
        this._handlerMap[name] = {
            callBack: cb,
            target: target
        };
    },

    handler: function (name, data, isRecord) {
        if (this._handlerMap[name] === undefined && (this._gameHandler[this._gameID] === undefined || this._gameHandler[this._gameID][name] === undefined))
            return;
        var item = this._handlerMap[name];
        if (item === undefined)
            item = this._gameHandler[this._gameID][name];
        cc.log(' 处理消息包:name ' + name);
        item.callBack.call(item.target, data, isRecord);
    },

    getGameProtoMsg: function (gameid) {
        var gameInfo = this._gamedict[gameid];
        return require(gameInfo.packet).PortoMsg;
    },

    initConnect: function () {
        var that = this;
        var gameInfo = this._gamedict[this._gameID];
        cc.director.preloadScene(gameInfo.scene.toLocaleLowerCase());
        var gamePacket = require(gameInfo.packet);
        ProtoManager.init(gamePacket.PortoMsg);
        packet.CommonPacketInfo.forEach(item => {
            if (item.block === undefined) {
                return; //当前消息是客户端发往服务器的，不需要注册
            }
            cc.log(' 注册监听事件:' + item.name);
            this._socket.on(item.name, function (data) {
                data = that.deCode(item.name, data);
                cc.log('pPacket._route = ' + item.name + ' data: ' + JSON.stringify(data));
                if (item.block) {
                    // cc.log(" 数据延时操作 ");
                    this._blockQueue.push({
                        name: item.name,
                        data: data
                    });
                } else {
                    this.handler(item.name, data, false);
                }
            }.bind(this));
        });

        gamePacket.PacketInfo.forEach(item => {
            if (item.block === undefined) {
                return; //当前消息是客户端发往服务器的，不需要注册
            }
            cc.log(' 注册监听事件:' + item.name);
            this._socket.on(item.name, function (data) {
                data = that.deCode(item.name, data);
                cc.log('pPacket._route = ' + item.name + ' data: ' + JSON.stringify(data));

                if (item.block) {
                    // cc.log(" 数据延时操作 ");
                    this._blockQueue.push({
                        name: item.name,
                        data: data
                    });
                } else {
                    this.handler(item.name, data, false);
                }
            }.bind(this));
        });
    },


    refresh: function () {
        this.close();
        this.reconnect(true);

    },

    close: function () {
        this.mCloseTime = new Date().getTime();

        cc.log("主动退出网络了喽！！！！");
        if (this._socket) {
            this._disConnectBackToHall = false;
            setTimeout(function () {
                if (this._socket) {
                    this._socket.disconnect();
                    delete this._socket;
                }
                this._socket = null;
            }.bind(this), 100);
        }
        this.stopForeverMsg();
        this._blockQueue = [];
        this._isConnect = false;
        this.unschedule(this.update);
        this._msgQueuec = [];
    },


    onDisConnect: function (err) {
        // tool.dismissWindowByName('loadingwin');
        tool.dismissWindowByName('loadingwin');
        cc.log(' onDisConnect = ' + err);
        if (typeof (err) != "undefined") {}

        this._isConnect = false;
        this.unschedule(this.update);
        this._msgQueuec = [];
        if (this._disConnectBackToHall) {
            tool.dismissWindowByName('loadingwin');
            if (this._isReconnect) {
                tool.showMessageBox("无法连接到服务器,请检查自己的网络后再试");
                if (cc.director.getScene().getName() != 'hall') {
                    cc.director.loadScene('hall');
                }
            } else {
                setTimeout(function () {
                    this.reconnect(true);
                }.bind(this), 200);
            }
        }
    },

    onConnect: function () {
        //连接上了。加入update
        this._isConnect = true;
        this.unschedule(this.update);
        this.schedule(this.update, 0);

        this.initConnect();
        if (this._connectListener) {
            this._connectListener();
        }
        if (this._isReconnect) {
            tool.dismissWindowByName('loadingwin');
            // var tid = 0;
            // if (this._scenePlay) {
            //     tid = this._scenePlay.mRoomID;
            // } else {
            //     var scnPlay = PlayerManager.getGameScene();
            //     if (scnPlay == null) {
            //         this._isReconnect = false;
            //         return;
            //     }
            //     tid = scnPlay.mRoomID;
            // }
            // if (tid == 0) {
            //     SceneManager.changeScene(GameConfig.SCENE_LOGIN);
            //     showMessageBox('网络连接失败,请重新登陆');
            // } else {
            //     NetManager.sendPacket(PacketID.BACKGAME, {
            //         id: PlayerManager.m_MySelf.m_dbid,
            //         tid: tid,
            //         ticket: ticket
            //     });
            // }
        }
        this._isReconnect = false;
    },

    onConnectFailed: function (isReconnect) {
        tool.dismissWindowByName('loadingwin');
        if (isReconnect) {
            tool.showMessageBox("无法连接到服务器,请检查自己的网络后再试");
            if (cc.director.getScene().getName() != 'hall') {
                cc.director.loadScene('hall');
            }
        } else {
            tool.showMessageBoxWithCancel("连接超时,是否重试?", function () {
                setTimeout(function () {
                    cc.windowManager.showWindowByNameWithDate('loadingwin', '重新连接服务器中，请稍等...');

                    this.reconnect()
                }.bind(this), 200);
            }.bind(this));
        }
    },

    onDisConnect: function (err) {
        tool.dismissWindowByName('loadingwin');
        cc.log(' onDisConnect = ' + err);
        if (typeof (err) != "undefined") {}

        this._isConnect = false;
        this.unschedule(this.update);
        this._msgQueuec = [];
        if (this._disConnectBackToHall) {
            tool.dismissWindowByName('loadingwin');
            if (this._isReconnect) {
                tool.showMessageBox("无法连接到服务器,请检查自己的网络后再试");
                if (cc.director.getScene().getName() != 'hall') {
                    cc.director.loadScene('hall');
                }
            } else {
                setTimeout(function () {
                    this.reconnect(true);
                }.bind(this), 200);
            }
        }
    },

    enCode: function (name, msg) {
        if (msg == null) {
            return '';
        }

        if (typeof (msg) == 'string') {
            msg = JSON.parse(msg);
        }

        //   return msg;
        try {
            cc.log('name[' + name + '] 加密前:' + JSON.stringify(msg));
            return ProtoManager.encodeToSocket(name, msg);
        } catch (error) {
            return '';
        }
    },

    /**
     * 解密
     */
    deCode: function (name, msg) {
        if (msg == null || msg == '') {
            return '';
        }
        // if (typeof (msg) == 'string') {
        //     msg = JSON.parse(msg);
        // }

        try {
            return ProtoManager.decodeFromSocket(name, msg);
        } catch (error) {
            cc.log('deCode [' + name + '] error' + error);
            return '';
        }
    },

    forTest: function () {
        this._blockQueue = [];
        this._isConnect = true;
        this._scenePlay = PlayerManager.getGameScene();
        this.unschedule(this.update);
        this.schedule(this.update, 0);
    },

    testPacket: function (route, data) {
        if (data != '' && typeof (data) == 'string') {
            data = this.deCode(data);
            data = JSON.parse(data);
        }
        var p = PacketManager.getPacket(route);
        if (p) {
            if (p._isBlock) {
                this._blockQueue.push({
                    'fun': p,
                    'msg': data
                });
            } else {
                //直接执行
                p.excute(this._scenePlay, data, false);

            }
        }
    },

    //==================== 录像相关的 =====================//
    initShareRecord: function (url, pid) {
        this.clearRecordMap();
        this.mIsShareRecord = true;
        this.mShowPid = pid;
        cc.windowManager.showWindowByNameWithDate('loadingwin', "录像文件加载中,请稍等...");

        //找到相应的游戏GMAEID
        var splitArr = url.split('/');
        if (splitArr.length == 0) {
            cc.windowManager.dismissWindowByName('loadingwin');
            tool.showMessageBox('录像文件加载错误');
            return;
        }

        this._gameID = Number.parseInt(splitArr[splitArr.length - 2]);
        tool.PlayerManager().mEnterGameId = gameid;
        ProtoManager.init(this.getGameProtoMsg(gameid));
        tool.getRecordFromUrl(url, function (data) {
            cc.windowManager.dismissWindowByName('loadingwin');
            if (data.success) {
                this.initWithRecord(ProtoManager.decodeFromReocrdStr(data.msg));
            } else {
                tool.showMessageBox('录像文件加载错误');
            }
        }.bind(this));
    },


    initWithRecordData: function (gameid, data, showId) {
        tool.PlayerManager().mEnterGameId = gameid;
        ProtoManager.init(this.getGameProtoMsg(gameid));
        this._gameID = gameid;
        this.mShowPid = showId;
        if (this.mShowPid == null)
            this.mShowPid = 1;

        this.initWithRecord(ProtoManager.decodeFromReocrdStr(data));
    },

    setRecordMap: function (url, idArr, idx) {
        this.mRecordUrl = url;
        this.mRecordFile = idArr;
        this.mNowIdx = idx;
    },

    clearRecordMap: function () {
        this.mRecordFile = [];
        this.mNowIdx = -1;
    },

    iniwWithUrl: function (url) {
        this.mShowPid = null;
        this.mIsShareRecord = false;
        cc.windowManager.showWindowByNameWithDate('loadingwin', "录像文件加载中,请稍等...");

        //找到相应的游戏GMAEID
        var splitArr = url.split('/');
        if (splitArr.length == 0) {
            cc.windowManager.dismissWindowByName('loadingwin');
            tool.showMessageBox('录像文件加载错误');
            return;
        }

        var gameid = Number.parseInt(splitArr[splitArr.length - 2]);
        tool.PlayerManager().mEnterGameId = gameid;
        ProtoManager.init(cc.NetManager().getGameProtoMsg(gameid));

        tool.getRecordFromUrl(url, function (data) {
            cc.windowManager.dismissWindowByName('loadingwin');

            if (data.success) {
                this.initWithRecord(ProtoManager.decodeFromReocrdStr(data.msg));
            } else {
                tool.showMessageBox('录像文件加载错误');
            }
        }.bind(this));
    },

    initWithRecord: function (data) {
        this.mUserData = data.shift();
        this.mRecordPlayerStr = JSON.stringify(this.mUserData.playinfo);
        this.mPacketReadIndex = 0;
        this.mRecordList = data;
        this.mIsPlayRecord = true;
        tool.PlayerManager().createReocrdPlayer(this.mUserData.playinfo, this._gameID, this.mShowPid);
        cc.director.loadScene(this.getGameScene().toLocaleLowerCase(), function () {
            var scene = cc.find('Canvas').getComponent(this.getGameScene());
            scene.setGameInfo(this.mUserData);
            this.mRecordList = data;
            this.recordStart();
        }.bind(this));
    },


    recordUpdate: function () {
        this.next();
    },


    recordStart: function () {
        this.unschedule(this.recordUpdate);
        this.schedule(this.recordUpdate, 1);
    },

    recordPause: function () {
        // this.unschedule(this.update.bind(this));
        this.unschedule(this.recordUpdate);
    },

    recordEnd: function () {
        this.unschedule(this.recordUpdate);
    },

    reBack: function () {
        if (this.mPacketReadIndex < 0)
            return;
        var packetInfo = this.mRecordList[this.mPacketReadIndex];
        var packet = PacketManager.getPacket(packetInfo['id']);
        if (packet) {
            packet.reBack(this._scenePlay, packetInfo['msg'], true);
        }
        this.mPacketReadIndex--;
    },


    next: function () {
        if (this.mPacketReadIndex >= this.mRecordList.length) {
            this.recordEnd();
            return;
        }
        var packetInfo = this.mRecordList[this.mPacketReadIndex++];
        this.handler(packetInfo.id, packetInfo.msg, true);
    },

    nextTime: function (time) {
        //下一个的时间变成这样
        this.unschedule(this.recordUpdate);

        setTimeout(function () {
            this.next();
            this.schedule(this.recordUpdate, time);
        }.bind(this), time);

    },

    rePlay: function () {
        var scenePly = tool.PlayerManager().getGameScene();
        if (scenePly) {
            scenePly.openScene();
            scenePly.openSceneWithData(GameData.GAMEDATA_RECORD);
        }

        this._scenePlay = scenePly;
        if (tool.PlayerManager().mEnterGameId == GAMEID.wfph) {
            scenePly.onRecord(this.mUserData, this.mShowPid);
        } else {
            tool.PlayerManager().createReocrdPlayer(JSON.parse(this.mRecordPlayerStr), this._gameID, this.mShowPid);
        }

        this.mPacketReadIndex = 0;
        this.recordStart();
    },

    nextGameRecord: function () {
        if (this.mNowIdx < this.mRecordFile.length - 1) {
            var scenePly = tool.PlayerManager().getGameScene();
            if (scenePly)
                scenePly.openScene();
            this.iniwWithUrl(this.mRecordUrl + this.mRecordFile[this.mNowIdx + 1]);
            this.mNowIdx++;
        }
    },

    perGameRecord: function () {
        if (this.mNowIdx > 0) {
            var scenePly = tool.PlayerManager().getGameScene();
            if (scenePly)
                scenePly.openScene();
            this.iniwWithUrl(this.mRecordUrl + this.mRecordFile[this.mNowIdx - 1]);
            this.mNowIdx--;
        }
    },

    over: function () {
        this.mIdx = 0;
        this.mRecordList = [];
        this.mIsPlayRecord = false;
    },

    getTextRecord: function (name) {
        //1042_879167.txt
        var data = readTxtFromFile(name);
        this.initWithRecord(ProtoManager.decodeFromReocrdStr(data));
    }
});


module.exports = NetManager;